from django.http import JsonResponse, HttpResponse
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.exceptions import ValidationError
from apps.note.models import Note
from apps.note.services.pdf_export_service import PDFExportService, PDFExportError
from .global_responses import BaseResponse
import logging
import json
import os

logger = logging.getLogger(__name__)

class PDFExportView(APIView):
    """提供PDF导出功能的API"""
    permission_classes = [IsAuthenticated]
    
    def post(self, request):
        """
        将笔记导出为PDF
        
        请求参数:
            - note_id: 笔记ID (可选，如果没有提供，则必须提供content参数)
            - content: Markdown格式的笔记内容 (可选，如果没有提供，则必须提供note_id参数)
            - title: 笔记标题 (可选)
            - filename: 下载时的文件名 (可选，默认使用title)
            - debug: 是否返回处理日志 (可选，默认false)
            - inline: 是否内联显示而非下载 (可选，默认false)
        
        返回:
            - PDF文件
        """
        try:
            # 尝试从JSON解析
            try:
                data = json.loads(request.body) if request.body else {}
            except ValueError:
                # 如果不是JSON格式，则使用常规表单数据
                data = request.data
            
            note_id = data.get('note_id')
            content = data.get('content')
            title = data.get('title', '导出笔记')
            filename = data.get('filename')
            debug = data.get('debug', False)
            inline = data.get('inline', False)
            
            # 检查参数
            if not note_id and not content:
                return BaseResponse.json_error('必须提供note_id或content参数')
            
            # 如果提供了note_id，从数据库获取笔记内容
            if note_id:
                try:
                    note = Note.objects.get(id=note_id, user=request.user)
                    content = note.content
                    title = title or note.title
                except Note.DoesNotExist:
                    return BaseResponse.json_error('未找到指定的笔记', status_code=404)
            
            # 确保内容非空
            if not content or not content.strip():
                return BaseResponse.json_error('笔记内容不能为空')
                
            # 设置文件名
            filename = filename or title
            if not filename.lower().endswith('.pdf'):
                filename += '.pdf'
                
            # 处理文件名中的特殊字符
            filename = self._sanitize_filename(filename)
            
            # 创建PDF服务实例
            pdf_service = PDFExportService()
            
            # 导出为PDF
            logger.info(f"开始生成PDF: 标题「{title}」, 内容长度: {len(content)} 字符")
            pdf_buffer = pdf_service.export_note_to_pdf(
                note_content=content,
                title=title
            )
            
            # 如果是调试模式，返回处理信息
            if debug:
                return BaseResponse.json_success({
                    'message': 'PDF生成成功',
                    'title': title,
                    'content_length': len(content),
                    'buffer_size': len(pdf_buffer.getvalue()),
                    'fonts_available': pdf_service._get_available_chinese_font()
                })
            
            # 返回PDF文件
            response = HttpResponse(pdf_buffer.getvalue(), content_type='application/pdf')
            
            # 根据inline参数决定是内联显示还是下载
            if inline:
                response['Content-Disposition'] = f'inline; filename="{filename}"'
            else:
                response['Content-Disposition'] = f'attachment; filename="{filename}"'
                
            return response
            
        except PDFExportError as e:
            logger.error(f"PDF导出错误: {str(e)}")
            return BaseResponse.json_error(str(e), status_code=getattr(e, 'http_status', 500))
        except Exception as e:
            logger.error(f"PDF导出未预期错误: {str(e)}", exc_info=True)
            return BaseResponse.json_error(f'导出PDF时发生错误: {str(e)}', status_code=500)
    
    def _sanitize_filename(self, filename):
        """清理文件名，移除不安全字符"""
        # 替换Windows文件名中不允许的字符
        for char in ['\\', '/', ':', '*', '?', '"', '<', '>', '|']:
            filename = filename.replace(char, '_')
        
        # 确保文件名不超过255个字符
        if len(filename) > 255:
            base, ext = os.path.splitext(filename)
            filename = base[:250] + ext
            
        return filename

class PDFTemplatesView(APIView):
    """获取可用的PDF模板"""
    permission_classes = [IsAuthenticated]
    
    def get(self, request):
        """
        获取系统中可用的PDF导出模板列表
        
        返回:
            - templates: 模板列表，每个模板包含id、name和description
        """
        try:
            return BaseResponse.json_success({
                'templates': [
                    {
                        'id': 'default',
                        'name': '默认模板',
                        'description': '简洁风格，适合所有类型的笔记'
                    },
                    {
                        'id': 'academic',
                        'name': '学术模板',
                        'description': '适合学术论文和研究笔记'
                    }
                ]
            })
        except Exception as e:
            logger.error(f"获取PDF模板列表错误: {str(e)}", exc_info=True)
            return BaseResponse.json_error(f'获取PDF模板列表失败: {str(e)}', status_code=500) 